// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"


////////////////////////////////////////////////////////////////////////////////
class Noeud {
// classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
// Remarque : la classe ne contient aucun constructeur
  public:


    virtual int  getValeur() =0 ; // méthode non implémentée qui rend la classe abstraite

    virtual void afficher(unsigned short indentation=0) { cout << setw(4*indentation) << " "; }
      // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre


    virtual ~Noeud() {} // présence d'un destructeur virtuel conseillée dans les classes abstraites


    bool getError();


    void setError(bool err);
  protected:

    bool error;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudSeqInst : public Noeud {
// classe pour représenter un noeud "sequence d'instruction"
// qui a autant de fils que d'instructions dans la séquence
  public: 
	

     NoeudSeqInst();   // construit une séquence d'instruction vide


    ~NoeudSeqInst() {} // à cause du destructeur virtuel de la classe Noeud


    int getValeur(); // évalue chaque instruction de la séquence
 

    void afficher(unsigned short indentation=0); // affiche la séquence d'instructions



    void ajouteInstruction(Noeud* instruction);  // ajoute une instruction à la séquence
  

   vector<Noeud *> getTabInst();

  private:


    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};


////////////////////////////////////////////////////////////////////////////////
class NoeudAffectation : public Noeud {
// classe pour représenter un noeud "affectation"
// composé de 2 fils : la variable et l'expression qu'on lui affecte
  public: 

     NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation


    ~NoeudAffectation() {} // à cause du destructeur virtuel de la classe Noeud



    int getValeur(); // évalue l'expression et affecte sa valeur à la variable


    void afficher(unsigned short indentation=0); // affiche l'affectation

  private:

    Noeud* variable;


    Noeud* expression;
};


////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurBinaire : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:


    NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit et symbole

   ~NoeudOperateurBinaire() {} // à cause du destructeur virtuel de la classe Noeud

    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur


    void afficher(unsigned short indentation=0); // affiche l'opération

  private:


    	Symbole operateur;

    	Noeud*  operandeGauche;

    	Noeud*  operandeDroit;
};


////////////////////////////////////////////////////////////////////////////////
class NoeudInstSi : public Noeud {
// classe pour représenter un noeud "Instruction Si"
//
	public:

		NoeudInstSi(vector<Noeud *> tabCond,vector<Noeud *> tabInst);

		int getValeur();

		void ajouteCond(Noeud * cond);

		void ajouteSeq(Noeud* seq);

		void afficher(unsigned short indentation=0); // affiche l'instruction si

		~NoeudInstSi() {} // à cause du destructeur virtuel de la classe Noeud

	private:

		vector<Noeud *> tabInst;	// pour stocker les sequences d'instrutions

		vector<Noeud *> tabCond;	// pour stocker les conditions

};

////////////////////////////////////////////////////////////////////////////////
class NoeudBoucle : public Noeud {
// classe pour représenter un noeud "Instruction Boucle"
//
	public:

		NoeudBoucle(Symbole tag,Noeud* condition, Noeud* seInst);



		int getValeur();
	
		void afficher(unsigned short indentation=0); // affiche l'instruction tant que

		~NoeudBoucle() {} // à cause du destructeur virtuel de la classe Noeud		

	protected:

		Symbole	tag;
		Noeud * condition;
		Noeud * seqInst;	// pour stocker les sequences d'instrutions
};

////////////////////////////////////////////////////////////////////////////////
class NoeudIO : public Noeud {
// classe pour représenter un noeud "L'instruction lire ou écrire"
//
	public:

		NoeudIO(Symbole sym, Noeud* variable);

		int getValeur();
			
		void afficher(unsigned short indentation=0); // affiche l'instruction Lire

		~NoeudIO() {} // à cause du destructeur virtuel de la classe Noeud		

	private:

		Symbole	sym;
		Noeud * variable;
};
////////////////////////////////////////////////////////////////////////////////
class NoeudError : public Noeud {
// classe pour représenter un noeud "error"
//
  public:

    NoeudError();
    int getValeur();    	
    void afficher();

    ~NoeudError() {} // à cause du destructeur virtuel de la classe Noeud    
};

////////////////////////////////////////////////////////////////////////////////
class NoeudPour : public NoeudBoucle {
// classe pour représenter un noeud "Instruction Pour" fille de la class NoeudBoucle
//
	public:
  		NoeudPour(Symbole taq,Noeud* condition,Noeud* seqInst,Noeud* affectInit,Noeud* affectIt);
		int getValeur();		
//		void afficher(unsigned short indentation=0); // affiche l'instruction tant que

		~NoeudPour() {} // à cause du destructeur virtuel de la classe Noeud	

	private:

		Noeud * affectInit;


		Noeud * affectIt;
};
////////////////////////////////////////////////////////////////////////////////
#endif /* ARBRE_H_ */
